package loger

import (
	"context"
	"fmt"
	"time"

	"gopkg.in/olivere/elastic.v5"
)

var (
	ErrCannotCreateIndex = fmt.Errorf("Cannot create index")
)

type ElasticHook struct {
	clt       *elastic.Client
	host      string
	index     string
	ctx       context.Context
	ctxCancel context.CancelFunc
}

type ElasticHookData struct {
	Timestamp string `json:"@timestamp"`
	Data      map[string]interface{}
	Level     string
	Message   string
}

func NewElasticHook(host string, index string) (*ElasticHook, error) {
	clt, err := elastic.NewClient(elastic.SetURL(host))
	if err != nil {
		return nil, err
	}

	ctx, cancel := context.WithCancel(context.TODO())
	exists, err := clt.IndexExists(index).Do(ctx)
	if err != nil {
		return nil, err
	}

	if !exists {
		ret, err := clt.CreateIndex(index).Do(ctx)
		if err != nil {
			return nil, err
		}
		if !ret.Acknowledged {
			return nil, ErrCannotCreateIndex
		}
	}
	return &ElasticHook{
		clt:       clt,
		host:      host,
		index:     index,
		ctx:       ctx,
		ctxCancel: cancel,
	}, nil
}

func (this *ElasticHook) Fire(entry *Entry) error {
	data := ElasticHookData{
		entry.Time.UTC().Format(time.RFC3339Nano),
		entry.Data,
		entry.Level.String(),
		entry.Message,
	}

	_, err := this.clt.
		Index().
		Index(this.index).
		Type("log").
		BodyJson(data).
		Do(this.ctx)

	return err
}

func (this *ElasticHook) Levels() []Level {
	return AllLevels
}
